
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;



/**
 * @项目名称：meter
 * @类名称：ZipTools
 * @类描述：采用zip压缩文件
 * @创建人：meter
 * @创建时间：2018年5月4日 上午10:25:09
 * @版权：Copyright@2018.All Rights Reserved
 * @version v1.0
 */
public class ZipTools {
  /**
   * @创建日期：2018年5月4日 下午1:37:22
   * @作者： meter
   * @描述：压缩多个文件的情况
   * @Title: zip
   * @param fileList
   * @param zipFile
   * @throws Exception
   */
  public static void zipFiles(List<File> fileList,File zipFile) throws Exception{
    System.out.println("zipFiles待压缩文件："+zipFile.getAbsolutePath());
    if(fileList != null){
      if(zipFile.exists()){//压缩文件已经存在，则只能单个添加
        for(File file:fileList){
          zip(zipFile,file);
        }
      }else{//不存在则新建
        // 创建zip输出流
        ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipFile), Charset.forName("UTF-8"));
        // 创建缓冲输出流
        BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream);
        for(File file:fileList){
          zipFile(file,zipOutStream,bufferOutStream);
        }
        //最后关闭输出流
        bufferOutStream.close();
        zipOutStream.close();
      }

    }
  }
  /**
   * @创建日期：2018年5月4日 下午1:44:55
   * @作者： meter
   * @描述：执行文件压缩
   * @Title: zipFile
   * @param file
   * @param zipOutStream
   * @param bufferOutStream
   * @throws IOException
   */
  private static void zipFile(File file,ZipOutputStream zipOutStream,BufferedOutputStream bufferOutStream) throws IOException{
    // 创建压缩文件实体
    ZipEntry entry = new ZipEntry(file.getName());
    // 添加实体
    zipOutStream.putNextEntry(entry);
    // 创建输入流
    BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(file));
    write(bufferInputStream, bufferOutStream);
    zipOutStream.closeEntry();
  }
  /**
   * @创建日期：2018年5月4日 下午1:37:01
   * @作者： meter
   * @描述：压缩单个文件
   * @Title: zip
   * @param zipFile
   * @param sourceFile
   * @throws Exception
   */
  public static void zip(File zipFile, File sourceFile) throws Exception {
    System.out.println("待压缩文件："+zipFile.getAbsolutePath());
    if (zipFile.exists()) {// 添加到已经存在的压缩文件中

      File tempFile=new File(zipFile.getAbsolutePath()+".tmp");
      // 创建zip输出流
      ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(tempFile), Charset.forName("UTF-8"));
      // 创建缓冲输出流
      BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream);
      ZipFile zipOutFile = new ZipFile(zipFile);

      Enumeration<? extends ZipEntry> entries = zipOutFile.entries();
      while (entries.hasMoreElements()) {
        ZipEntry entry = entries.nextElement();
        System.out.println("copy: " + entry.getName());
        zipOutStream.putNextEntry(entry);
        if (!entry.isDirectory()) {
          write(zipOutFile.getInputStream(entry), bufferOutStream);
        }
        zipOutStream.closeEntry();
      }
      zipOutFile.close();//记得关闭zip文件，否则后面无法删除原始文件
      ZipEntry entry = new ZipEntry(sourceFile.getName());
      // 添加实体
      zipOutStream.putNextEntry(entry);
      BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(sourceFile));
      write(bufferInputStream, bufferOutStream);
      //最后关闭输出流
      bufferOutStream.close();
      zipOutStream.close();
      boolean flag=zipFile.delete();
      if(flag){
        tempFile.renameTo(zipFile);
      }else{
        System.out.println("删除文件失败。");
      }
    } else {// 新创建压缩文件
      // 创建zip输出流
      ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipFile), Charset.forName("UTF-8"));
      // 创建缓冲输出流
      BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream);
      // 创建压缩文件实体
      ZipEntry entry = new ZipEntry(sourceFile.getName());
      // 添加实体
      zipOutStream.putNextEntry(entry);
      // 创建输入流
      BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(sourceFile));
      write(bufferInputStream, bufferOutStream);
      //最后关闭输出流
      bufferOutStream.close();
      zipOutStream.close();
    }

  }
  /**
   * @创建日期：2018年5月4日 下午2:09:37
   * @作者： meter
   * @描述：读写zip文件
   * @Title: write
   * @param inputStream
   * @param outStream
   * @throws IOException
   */
  private static void write(InputStream inputStream,OutputStream outStream) throws IOException{
    byte[] data=new byte[4096];
    int length=0;
    while((length=inputStream.read(data)) != -1){
      outStream.write(data,0,length);
    }
    outStream.flush();//刷新输出流
    inputStream.close();//关闭输入流
  }

  /**
   * @创建日期：2018年5月4日 下午3:07:55
   * @作者： meter
   * @描述：压缩指定目录下所有文件
   * @Title: zipDirectory
   * @param dirFile
   * @param zipFile
   * @throws IOException
   */
  public static void zipDirectory(File dirFile,File zipFile) throws IOException{
    if(dirFile != null && dirFile.isDirectory()){
      if(zipFile == null){
        zipFile=new File(dirFile.getAbsolutePath()+".zip");
      }
      String dirName=dirFile.getName()+File.separator;
      // 创建zip输出流
      ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(zipFile), Charset.forName("UTF-8"));
      // 创建缓冲输出流
      BufferedOutputStream bufferOutStream = new BufferedOutputStream(zipOutStream);
      dealDirFile( dirFile,dirName,bufferOutStream,zipOutStream);

      //最后关闭输出流
      bufferOutStream.close();
      zipOutStream.close();
    }else{
      System.out.println("["+dirFile.getName()+"]不是一个文件夹,或者不存在。");
    }
  }
  /**
   * @创建日期：2018年5月4日 下午4:38:46
   * @作者： meter
   * @描述：处理目录文件
   * @Title: dealDirFile
   * @param dirFile
   * @param parentDir
   * @param bufferOutStream
   * @param zipOutStream
   * @throws IOException
   */
  private static void dealDirFile(File dirFile,String parentDir, BufferedOutputStream bufferOutStream, ZipOutputStream zipOutStream) throws IOException{
    File[] fileList=dirFile.listFiles();
    for(File file:fileList){
      if(file.isFile()){
        // 创建压缩文件实体
        ZipEntry entry = new ZipEntry(parentDir+file.getName());
        // 添加实体
        zipOutStream.putNextEntry(entry);
        // 创建输入流
        BufferedInputStream bufferInputStream = new BufferedInputStream(new FileInputStream(file));
        write(bufferInputStream, bufferOutStream);
      }else{
        dealDirFile(file,  parentDir+file.getName()+File.separator,  bufferOutStream,  zipOutStream);
      }
    }
  }
  /**
   * @创建日期：2018年5月4日 下午3:22:11
   * @作者： meter
   * @描述：重载zipDirectory
   * @Title: zipDirectory
   * @param dirPath
   * @param zipPath
   * @throws IOException
   */
  public static void zipDirectory(String dirPath,String zipPath) throws IOException{
    if(zipPath==null || "".equals(zipPath)){
      zipDirectory(new File(dirPath),null);
    }else{
      zipDirectory(new File(dirPath),new File(zipPath));
    }
  }
  //------------------------------------------------米特华丽的分割线----------------------------------------------------------------------------------------

  /**
   * @创建日期：2018年5月4日 下午4:00:41
   * @作者： meter
   * @描述：解压文件
   * @Title: unzip
   * @param zipFile
   * @param destDir
   * @throws IOException
   */
  public static void unzip(File zipFile, File destDir) throws IOException {
    ZipFile zipOutFile = new ZipFile(zipFile,Charset.forName("gbk"));
    Enumeration<? extends ZipEntry> entries = zipOutFile.entries();
    while (entries.hasMoreElements()) {
      ZipEntry entry = entries.nextElement();
      if(entry.isDirectory()){
        File tempFile = new File(destDir.getAbsolutePath()+File.separator+entry.getName());
        if (!tempFile.exists()) {
          tempFile.mkdirs();
        }
      }else{
        File tempFile=new File(destDir.getAbsolutePath()+File.separator+entry.getName());
        checkParentDir(tempFile);
        FileOutputStream fileOutStream=new FileOutputStream(tempFile);
        BufferedOutputStream bufferOutStream = new BufferedOutputStream(fileOutStream);
        write(zipOutFile.getInputStream(entry),bufferOutStream);
        bufferOutStream.close();
        fileOutStream.close();
      }
    }
    zipOutFile.close();//记得关闭zip文件
  }

  /**
   * @创建日期：2018年5月4日 下午4:37:41
   * @作者： meter
   * @描述：验证父目录是否存在，否则创建
   * @Title: checkParentDir
   * @param file
   */
  private static void checkParentDir(File file){
    if(!file.getParentFile().exists()){
      file.getParentFile().mkdirs();
    }
  }

}
